// login
// createbuild
// dostudy
// arbite jobs
// job mode
function CController() {
	this.jobmode = '';
	
	em.ahelper = new CActionHelper();
	em.ahelper.initialize();
	
	var self = this;
	em.cbs.sectimer.add( function() {
		// debug.log(this, 'self',self, '2222' );
		self.sectimerFn();
	});
	
	// start sec timer after user changed 
	em.cbs.userchanged.add ( function() {
			console.log( ' Start timer ... sec '); 
			self.sectimerId = setInterval( function() {
												em.cbs.sectimer.fire();
												// console.log( ' sec timer .fire !!');	
									}, 1 * 1000);
						});
						
	// em.cbs.forcestop.add ( );
};

CController.prototype = {
	objName: 'Controller: ',
	
	
	// from login DLG. :  entry fn for login :  -
	// set cur user -> > start GM   
	login: function(username){
		
		debug.log(this, username);
		
		em.cbs.startuserchange.fire();
		
		
		// ACC mgr ���듯빐 set user .. DB, cstl.. .�ㅼ젙. 
		em.accmgr.setCurUser(username);

		
		// first try start GM 
		em.accmgr.startGM(username);
		
	},
	
	// from monotor... 
	doAutoHnt: function(cstl_idx, dfd) {
		
		em.infoview.setAutoHntStart();
		var outer = this;
				
				
		if ( ! em.hntmgr ) {
			if ( CDB.getCurUserOptions().hntmgr ==  2 ) {
				debug.log( this, '~~~~~~~~~~~~~');
				em.hntmgr = new CHuntMgr2();
			}else {
				em.hntmgr = new CHuntMgr();
			}
			em.hntmgr.initialize();
		}
		
		if ( this.bIsDoing() ) return;
			
		this.jobmode = 'AutoHnt';
		
		debug.log(this,cstl_idx , " start !!! ");
		
		// TOD : cb 는  모두 cstl mgr 로 nity 하도록 변경..!!!  
		var autohnt_param = {
					idx: cstl_idx,
					DAsArr: em.accmgr.getCurDAs() ,		//  각 cstl 시작시마다,, 갱신 ? ,,,  	
		};		
		
		// TODO  : startAuto 를  deffered 로 변경. 
		em.hntmgr.startAutoHnt(autohnt_param).always(
				 function() {
					debug.log( outer, 1, 'this', this,  outer.jobmode + ' !!! ');
					outer.finishDone();
					}
		).done(function(ret_code){		/// ret_code :  hnting 결과 . 
				 
				/// caller 에게 resolve   전달.
				// called from box :  to box
				// called from monotor : to monotor  
				debug.log( outer, 3, outer.jobmode + ' startAutoHnt Done !!! ');
				em.cbs.autoCstlAttDone.fire(cstl_idx, ret_code);
				dfd.resolve();
				
				/// 무조건 job monotor 로 부터 오기 때문에.. resolve 만 하면 끝.. 
	
				
		}).fail( function() {		// hnt start fail !!  from some external reasons 
				debug.log( outer, 3, outer.jobmode + ' Fail !!! ');
				// always set resolve to inform cur job is finished...!!!
				dfd.resolve();	
			});
				
	},	
	
	
	
	doHDrin: function(dfd) {
		if ( ! em.hdrinmgr ) {
			em.hdrinmgr =  new CHDrinMgr();
		}
		if ( this.bIsDoing() ) return;
			
		this.jobmode = 'HDrin';
		
		var self = this;
		em.hdrinmgr.doHDrin().always( function() {
										debug.log( self, 3, self.jobmode + '  em.hdrinmgr.startWave() DONE !!! ');
										self.finishDone();
										dfd.resolve();		
										}
			);
				
	},
	
	
	doSP30Action: function( dfd) {

		if ( this.bIsDoing() ) return;
			
		this.jobmode = 'doSP30Action';
		
		var self = this;
		
		em.spactmgr.doAction().always( function() {
									debug.log( self, 3, self.jobmode + '  em.spactmgr.doAction DONE !!! ');
									self.finishDone();
						
										}
			).done ( function() {
									dfd.resolve();
			}).fail( function() {
									dfd.reject();
									// devide : reset stack.. depth. 
									setTimeout( function() {
										debug.log ( this, ' GO next Acc : ');
										// when fail : do righ after 
										em.jobmonitor.addJob( {name: 'SP30ACTION', fn: em.jobmonitor.doSP30Action, param: undefined });
										em.jobmonitor.doMonitor();
										
									} , 100);
			});
				
	},
	
	doBuySP30: function(arg, dfd) {

		if ( this.bIsDoing() ) return;
			
		this.jobmode = 'BuySP30';
		
		var self = this;
	// use direct tasks		
		em.tasks.buySP30 (arg.sid , arg.type,  arg.price, arg.step3_price, 
				function(result){
					debug.log( self, self.jobmode , 'result:', result);
					
					self.finishDone();
					if ( result.code == 0 ) {
						// update view
						em.util.print_result( 'SP30::  Purchase: Success') 
					}

					dfd.resolve();	
					// em.infoview.(result);
				});
				
	},
	
	
	// param: { 'cstlidx': cstl_idx, 'id' :tem_id, 'type': tem_type } }
	doEnhance: function(arg, dfd) {
		if ( this.bIsDoing() ) return;
			
		this.jobmode = 'doEnhance';
		
		var self = this;
		
		debug.log(this, 'doEnhance arg', arg);
		
		if ( arg == 'redo' ) {
			arg = self.doEnhance.arg;		// re do with prev arg
			debug.log(this, ' REDO: enhance : arg ' , arg);
		} else {
			// store prev arg for redo 
			self.doEnhance = self.doEnhance || {};
			self.doEnhance.arg = arg;
		}
		// use direct tasks		
		em.tasks.uniEnhance(arg.cstlidx , arg.id,  arg.type, 
				function(data, tem){
					debug.log( self, self.jobmode , 'data:', data);
					
					
					self.finishDone();
					
					if ( typeof data === 'number' ) {
						dfd.reject();
					} else {
						// calc nexttime
						if ( data && data.ret.cd ) {
							data.nexttime = new Date( $.now() + (data.ret.cd) * 1000) ;
						} else if ( data && data.code == 0 ){
							// next 15min 
							data.nexttime = new Date( $.now() + 15*60 * 1000) ;
						}
						
						dfd.resolve();	
					} 
					
					/// store nexttime 
					self.doEnhance = self.doEnhance || {};
					self.doEnhance.nexttime = data ? data.nexttime : -1;
					
					// update view 
					em.infoview.updateEnhance(data, tem)
				});
				
	},

	doHFealty: function(dfd) {
		if ( ! em.hfealtymgr ) {
			em.hfealtymgr =  new CFealtyMgr();
		}

		if ( this.bIsDoing() ) return;
		
		var self = this;		
		this.jobmode = 'HFealty';	
		em.hfealtymgr.startWave().always( function() {
										debug.log( self, 3, self.jobmode + ' !!! ');	
										self.finishDone();
										dfd.resolve();	
										}
			);
				
	},



	// scan 
	doScanDAsArr: function(args, dfd) {
		if ( this.bIsDoing() ) return;
		
		this.jobmode = 'doScanDAsArr';				
		// send scan 
		var result = true;
		var errorcode = 0 ;
		var complete = false;
		
		var self = this;
		var cit_num =  CDB.getCurUserCtsl()[0].id
		
		var scan_param = {
				// att param : x, y, tr: { s : n , o : n }, success_cb , error_cb
				citnum : cit_num,
				tr: { s:1},
				success_cb : succ, 
				error_cb : error,
				notify_cb : noty, 
			};
			
		if( !this.scan ) this.scan = {};
			
		var DAsArr  = CDB.getCurUserInfo().DAsArr[args.arrIdx];
		var curIdx = args.startIdx;
		var endIdx = args.endIdx;
		
			
		// remove already added favs list 
		function gotFavs(data) {
				console.log('got favs in Scan');
				var favs   = data.ret.favs;



				// proceed scan actions
		
				// sort 
				var mine = em.cstlmgr.getCstlPos(0); 
				var my_x = mine.x; 
				var my_y = mine.y;
				
				// sort  by mine distance 
				DAsArr.sort(function(a,b){
						//  max 처리 .!!!   10 <- 280 - > 260 :  30 !! 
						// 10 - 260  ; 250 ,   280 - 250 : 30  ,  min ( 250, 30)
						//  50 , 80 : 50 -80 : 30,    280 - 30 = 250 ; 
						// 160, 280 : 120 ,  280 - 120 : 160 
						var diff_ay = Math.min( Math.abs(my_y -a.y) ,  280 - Math.abs(my_y - a.y)  );
						var diff_ax = Math.min( Math.abs(my_x -a.x) ,  280 - Math.abs(my_x -a.x)  );
	
						var diff_by = Math.min( Math.abs(my_y -b.y) ,  280 - Math.abs(my_y - b.y)  );
						var diff_bx = Math.min( Math.abs(my_x -b.x) ,  280 - Math.abs(my_x -b.x)  );
						
						var dis_a = Math.pow(diff_ax,2) + Math.pow( diff_ay, 2) ;
						var dis_b = Math.pow(diff_bx,2) + Math.pow( diff_by, 2) ;
						
						// var dis_a = Math.pow(Math.abs(my_x - a.x ),2) + Math.pow( Math.abs(my_y- a.y), 2) ;
						// var dis_b = Math.pow(Math.abs(my_x - b.x ),2) + Math.pow( Math.abs(my_y- b.y), 2) ;
						return dis_a - dis_b;
					}); 
								
					// scanStart
								
				// store sorted arr 
				self.scan.DAsArr = DAsArr;

		
				scan_param.x = DAsArr[curIdx].x;
				scan_param.y = DAsArr[curIdx].y;
				em.scaning.doScan(scan_param);
			}
			
			// get fav list 
			var favs_param = { cb : gotFavs };
			em.ahelper.getFavs(favs_param);			
			return;
			
		

			function goNextScan() {
				scan_param.x = DAsArr[curIdx].x;
				scan_param.y = DAsArr[curIdx].y;
				em.scaning.doScan(scan_param);
			};
 	
			function succ (travel_secs) {
				result = true;
				complete = true;
				console.log('complete !! scan done ' );
				em.util.print_result('Done req sacn :' + curIdx );
				curIdx++;
				
				// save longest 
				if ( !self.longest_traveltime || self.longest_traveltime.getTime() < $.now() + travel_secs*1000) {
					self.longest_traveltime = new Date($.now() + travel_secs*1000);
					debug.log(this, 'tr time : ',self.longest_traveltime ,  CUtil.TimeToString(self.longest_traveltime));
				} 
				
				//  end condition!!
				if ( curIdx > endIdx) {
					em.util.print_result('all done req sacn :' + curIdx + ' , ' + CUtil.TimeToString(self.longest_traveltime));
// 					 resolv
					

					// add next seq job 
					setTimeout( function() { em.jobmonitor.addJob( {name: 'checkResultAddFav', fn: em.jobmonitor.checkResultAddFav, param: [] });
									} , (self.longest_traveltime.getTime() - $.now()) );
					
					dfd.resolve();
					self.finishDone();
					return;
				}
				
				setTimeout( function() { goNextScan(); }, CUtil.RandTime(3000));
			};

			function error(code) {
				result = false;
				errorcode = code;
				complete = true; 
				debug_log("Erro CB is called !!! errcode:" + errorcode + ' curindex : ' + curIdx);
				dfd.reject();
				self.finishDone();
			} ;
			
			function noty(msg) {
			console.log(msg);
			em.util.print_result(msg );
			};
		},
/*
		check result 
*/
		checkResultAddFav: function(dfd) {
			var self = this;
				var result = true;
				var errorcode = 0 ;
				var complete = false;
				
				// var DAsArr = em.data.data_world6star_sort;
				
				var DAsArr;
				if ( ! this.scan ) {
					this.scan = {};
					this.scan.DAsArr = CDB.getCurUserInfo().DAsArr[0];
				}
				DAsArr = this.scan.DAsArr;
				
				// to check new das  : deep copy 
				var ori_DAs = DAsArr.slice();
				
				var scanres_param = {
				// citnum : 3070,
				DA_arr: DAsArr,
				maxpage: 10,
				success_cb : succ, 
				error_cb : error,
				notify_cb : noty, 
				};
				
				
				// !!!! move cstl  : to update scan result !!!!!
				em.cbs.cstlmove1done.add( this.cb_cstlmove = function( ){ startResultScan();}  );
				em.cstlmgr.moveCstlAt(0);
					
				function startResultScan() {
					em.cbs.cstlmove1done.remove( this.cb_cstlmove);
					em.resultscan = new CResultScan();
					em.resultscan.initialize();
					
					em.resultscan.doResultScan(scanres_param);
				};
				
				function succ () {
					result = true;
					complete = true;
					$.each( DAsArr, function(i,da) {
						
						//if ( i % 20  == 0 )  	em.util.print_result('' + i );
						var str = ' {x:' + da.x  + ', y:' + da.y ;
						if (da.h || da.n) 
							str += ', h:' + da.h + ', n:' + da.n ;
						str += ' } ,';
						em.util.print_result(str);
						
					});
					
					
					// print only newly found .. 
					em.util.print_result('\n\n New Found DAs!!!! \n\n');
					em.util.print_result('\n\n New Found DAs!!!! \n\n');
					em.util.print_result('\n\n New Found DAs!!!! \n\n');
					
					$.each( DAsArr, function(i,da) {
						if ( ori_DAs[i].h ||  ori_DAs[i].n  
							 ||  ( ! da.h && ! da.n ) )  return;
							 
						// if ( ( ! ori_DAs[i].h  && !  ori_DAs[i].n) 
						 // && ( da.h || da.n ) ) return;
						var str = ' {x:' + da.x  + ', y:' + da.y ;
						if (da.h || da.n) 
							str += ', h:' + da.h + ', n:' + da.n ;
						str += ' } ,';
						em.util.print_result(str);
					});
					
					dfd.resolve();
					self.finishDone();
				};
				
				function error(code) {
					result = false;
					errorcode = code;
					complete = true; 
					debug_log("Erro CB is called !!! in test case :" + errorcode);
					dfd.reject();
				} 
				
				function noty(msg) {
					// console.log(msg);
					em.util.print_result(msg );

				}
	},
	

/*
	PV ======================================
*/
	doLootUs_PVP: function(args, jobdfd) {

		if ( this.bIsDoing() ) return;
		
		var self = this;		
		this.jobmode = 'doLootUs_PVP';	
		
		
				// get  best one us 
		// var us = em.worldDA.getBestUs();

		var dfd = $.Deferred();
		
		
		var us  = args[0];
		
		var trs = {};
		// specified o num
		if ( us.onum && us.onum > 0) {
			trs.o = us.onum ;
		} else {
			// calc trs 
			if ( us.lv < 20 ) {
				trs.o = 50;	
			} else if ( us.lv < 30 ) {
				trs.o = 100;
			} else if ( us.lv < 40 ) {
				trs.o = 400;
			} else {
				debug.log(this, ' US LV is too high ' , us , us.lv , us.name);
				trs.o = 1500;
			}		
		}
		
		// lanu
		if ( us.lnum && us.lnum > 0) {
			trs.l = us.lnum ;
		} else {
			trs.l = 0;
		}
		
		
		debug.log(this, 'start . loo ', trs, us, us.lv);
		var ret_cb = args[1];
		$.when(dfd).then( function(result) {
						debug.log(this, 'Loot  Success!!');
						 jobdfd.resolve();
						 ret_cb.fire(us, result);
						 self.finishDone();
						}
					, function(result){
							alert(' Loot fail');
							jobdfd.reject();
							ret_cb.fire(us);
							self.finishDone();
						}, 
					function(msg){ console.log(msg);}	);

		
		em.tasks.lootUs_PV( us, trs, dfd);
	},

	UpDur_PVP: function(jobdfd) {

		if ( this.bIsDoing() ) return;
		
		var self = this;		
		this.jobmode = 'UpDur_PVP';	

		var dfd = $.Deferred();

		function processRet(result) {
			 jobdfd.resolve();
			 self.finishDone();
				 		
			debug.log( self, 'this', self, result);
			
			if ( !self.dur ) self.dur = {};
			
			self.dur.code = result.code;
			self.dur.remains =  result.ret[1];
			self.dur.remaind =  result.ret[0];

			// 8903 : not avaliable !!1 
			if ( self.dur.code != 0 ) {
				self.dur.endtime = new Date($.now() +  5 * 60 * 1000);		// check next after 5min 
			} else {
				self.dur.endtime = new Date($.now() + self.dur.remains * 1000);
			}
			
			 // update to UI 
			 em.infoview.updateDur(result);
		};
		
		// only success
		$.when(dfd).then( function(result) {
						debug.log(this, 'ret dur  Success!!', result);
						processRet(result);
						}
		);

		
		em.tasks.upDurability_PVP( dfd);
	},


		// get next time att
	checkInterval_PVP: function(jobdfd) {

		if ( this.bIsDoing() ) return;
		
		var self = this;		
		this.jobmode = 'checkInterval_PVP';	
		var cstlinfo = em.cstlmgr.getCurCstl();
		function getMineInfo(usarr){
// 			[48,12,-1,[100,"[Hip] james!!",2,7,"",0,0,1,257336,0,100,"james!!",[0,0,null,5],0,100,0]],
			var us = usarr.filter ( function(el){
					return (el[2] == -1 ) && (el[3][0] == cstlinfo.id); 
				})[0];
			
				// sleep time  , du ,  next 
			// 41648,96,0]],
			var mine_info = {};
			var sleeptime = us[3][13];
			mine_info.sleepdate = new Date( $.now() + (sleeptime - 15) * 1000) ;
			mine_info.dur = us[3][14];
			mine_info.nexttime = us[3][15];
			if ( sleeptime != 0  ) {
				mine_info.nexttime = sleeptime;
			}					
			// before 2min  
			mine_info.nextdate = new Date( $.now() + (mine_info.nexttime ) * 1000) ;
			
			// update view
			em.infoview.updateMine_PVP(mine_info);
			
			
			 // add hunt job without flag  2 ~ 3 jobs.. to send all trs 
			 // 2 min before
			 if ( (mine_info.nextdate.getTime() - $.now() ) < 2*60*1000 )  {
				debug.log(this,  ' add Auto Hnt job before mine  endtime  2min ' , mine_info.nextdate.getTime() , ($.now() - 6*60*1000)  );
				em.jobmonitor.addJob( {name: 'StartCstlHnt', fn: em.jobmonitor.startAutoHnt, param: [] });
				em.jobmonitor.addJob( {name: 'StartCstlHnt', fn: em.jobmonitor.startAutoHnt, param: [] });
				// em.jobmonitor.addJob( {name: 'StartCstlHnt', fn: em.jobmonitor.startAutoHnt, param: [] });
			 }
				 
			// assign next action 
			 jobdfd.resolve();
			 self.finishDone();
			 return;
		}
		

		debug.log(this, ' Search MINE : ' , cstlinfo.x, cstlinfo.y);
		 var param = { x: cstlinfo.x , y: cstlinfo.y , cb : getMineInfo};
		 em.ahelper.worldMap(param);
		// em.tasks.getMineWorldInfo_PVP( dfd);
	},



	
	
	bIsDoing: function() {
		if ( this.jobmode != '') {
			debug.log( this, 3, 'Cur Job is '+ this.jobmode);
			return true;
		}
		return false;
	},
	
	finishDone: function() {
		debug.log( this, 2, 'Cur Job is '+ this.jobmode +' is finishDone !!!');
		this.jobmode = '';
	},	
	
	
	
	
	/*
		 timer 
	*/
	
	// timer job 
	sectimerFn: function() {
		em.cstlmgr.descCds();
		
	},
};